/*
    This file is part of libcloak.

    libcloak is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    libcloak is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with libcloak.  If not, see <http://www.gnu.org/licenses/>.

*/



#include "../include/Resource.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>



namespace Cloak
{
using namespace std;

// Buffer used by libcurl.
struct buffer
{
	int len;
	char *data;
};


// Callback for curl to read data into a buffer
size_t curl_callback(void* ptr, size_t size, size_t nmemb, void* stream)
{
	// We read the data we just got into a struct buffer.
	// It has fields to keep track of the length of the data
	// and the data itself.
	struct buffer *buf = (struct buffer *) stream;
	
	if(buf->data == NULL)
	{
		buf->len = size*nmemb;
		buf->data = (char*)malloc(size*nmemb+1);
		strncpy(buf->data, (char*)ptr, size*nmemb);
		buf->data[size*nmemb] = '\0';
	}
	else
	{
		buf->len += size*nmemb;
		buf->data = (char*)realloc(buf->data, buf->len);
		strncat(buf->data, (char*)ptr, size*nmemb);
	}
	
	return size*nmemb;
}

Resource::Resource(): loaded(false)
{
}

Resource::Resource(Resource &old): loaded(old.loaded), name(old.name)
{
}

// Shorthand resource loading code
char *Resource::loadResource(const string &location)
{
	size_t rlen;
	return loadResource(location, &rlen);
}
	
// Primary resource loading code, deal with urls
char *Resource::loadResource(const string &location, size_t *rlen) 
{
	string type = "file";
	string path = "";
	
	string::size_type loc = location.find("://", 0);
	
	// If we found the delimited, get the type, otherwise we use the 
	// default of file.
	if(loc != string::npos)
	{
		type = location.substr(0, loc); 
		path = location.substr(loc + 3);
	}
	else
	{
		path = location;
	}
	
	
	// For files just read in the whole file and return
	if(type == "file")
	{
		
		FILE* fd = fopen(path.c_str(), "r");
		
		
		// Failed to open file
		if(fd == NULL)
			return false;
		
		fseek(fd, 0, SEEK_END);
		int flen = ftell(fd);
		rewind(fd);
		
		char *buf = new char[flen];
		size_t rval = fread(buf, flen, 1, fd);
		
		if(rval == 0)
		{
			cerr << "Warning: Libcloak failed to read " << path << endl;
		}
		
		*rlen = flen;
		
		fclose(fd);
		return buf;
		
	}
	// For HTTP check if we have CURL, if so fetch.
	else if(type == "http" || type == "https" || type=="ftp")
	{
		
		#ifndef HAVE_CURL
		cerr << "libcloak compiled without CURL support\nAborting\n";
		exit(1);
		#else
		
		
		struct buffer* netbuf = new struct buffer;
		netbuf->data = NULL;
		netbuf->len = 0;
		
		CURL* ch = curl_easy_init();
		curl_easy_setopt(ch, CURLOPT_URL, location.c_str());
		curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, curl_callback);
		curl_easy_setopt(ch, CURLOPT_WRITEDATA, netbuf);
		curl_easy_perform(ch);
		
		*rlen = netbuf->len;
		
		return netbuf->data;
		
		delete netbuf;
		
		return NULL;
		
		#endif
	}
	else
	{
		cerr << "Warning: libcloak given bad URL type: "<<type<<endl;
		
		return NULL;
	}
}

bool Resource::isLoaded()
{
	return loaded;
}


}